import { AfterViewInit, Component, ElementRef, Inject, Input, OnInit, ViewChild } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { Router } from '@angular/router';
import { NzModalService } from 'ng-zorro-antd';
import { timer } from 'rxjs';
// import { fromEvent, Subscription } from 'rxjs';
import { AppStoreModule } from '@store/index';
import { select, Store } from '@ngrx/store';
import { CurrentActions } from '@store/reducers/player.reducer';
import { findIndex, shuffle} from '@utils/array';
import { Singer, Song } from '@services/data-types/common.type';
import { PlayMode } from '@share/wyy-ui/wyy-player/player-types';
import {
  getCurrentAction,
  getCurrentIndex,
  getCurrentSong,
  getPlayer,
  getPlayList,
  getPlayMode,
  getSongList
} from '@store/selectors/player.selector';
import { WyyPlayerPanelComponent } from './wyy-player-panel/wyy-player-panel.component';
import { BatchActionsService } from '@store/batch-actions.service';
import { animate, AnimationEvent, state, style, transition, trigger } from '@angular/animations';
import { ModalTypes, ShareInfo } from '@store/reducers/member.reducer';
import { User } from '@services/data-types/member.type';

enum TipTitles {
  Add = '已添加到列表',
  Play = '播放器初始化完成'
}

@Component({
  selector: 'app-wyy-player',
  templateUrl: './wyy-player.component.html',
  styleUrls: ['./wyy-player.component.less'],
  animations: [trigger('showHide', [
    state('show', style({ bottom: 0 })),
    state('hide', style({ bottom: -71 })),
    transition('show=>hide', [animate('0.3s')]),
    transition('hide=>show', [animate('0.1s')])
  ])]
})
export class WyyPlayerComponent implements OnInit, AfterViewInit {
  percent = 0;
  bufferPercent = 0;
  volume = 50;
  songReady = false;
  playing = false;
  songList: Song[];
  playList: Song[];
  playMode: PlayMode;
  currentIndex = 0;
  currentSong: Song;
  duration: number;
  currentTime: number;
  // 播放列表面板
  showPanel = false;
  // 歌曲音量面板
  showVolumePanel = false;
  // 是否点击了播放器内部区域
  bindFlag = false;
  // 是否点击了播放器以外的区域
  // winClicked: Subscription;
  // 记录切换播放模式图标点击的次数
  modeCount = 0;
  // 播放器显示/隐藏状态
  playerVisible = 'hide';
  // 播放器是否锁定
  isLocked = false;
  // 播放动画标识
  animating = false;
  // 控制tooltip提示语
  controlToolTip = {
    title: '',
    show: false
  };
  private audioEle: HTMLAudioElement;
  @Input() user: User;
  @ViewChild('audio', { static: true }) private audio: ElementRef;
  @ViewChild(WyyPlayerPanelComponent, { static: false }) private playerPanel: WyyPlayerPanelComponent;
  constructor(
    private router: Router,
    private store$: Store<AppStoreModule>,
    private nzModalServe: NzModalService,
    private batchActionsService: BatchActionsService,
    @Inject(DOCUMENT) private doc: Document) {}
  ngOnInit() {
    const appStore$ = this.store$.pipe(select(getPlayer));
    appStore$.pipe(select(getSongList)).subscribe(list => this.watchList(list, 'songList'));
    appStore$.pipe(select(getPlayList)).subscribe(list => this.watchList(list, 'playList'));
    appStore$.pipe(select(getCurrentIndex)).subscribe(index => this.watchCurrentIndex(index));
    appStore$.pipe(select(getPlayMode)).subscribe(mode => this.watchPlayMode(mode));
    appStore$.pipe(select(getCurrentSong)).subscribe(song => this.watchCurrentSong(song));
    appStore$.pipe(select(getCurrentAction)).subscribe(action => this.watchCurrentAction(action));
  }
  ngAfterViewInit() {
    this.audioEle = this.audio.nativeElement;
  }
  get picUrl(): string {
    return this.currentSong ? this.currentSong.al.picUrl : 'http://s4.music.126.net/style/web2/img/default/default_album.jpg';
  }
  private watchList(list: Song[], type: string) {
    this[type] = list;
  }
  private watchCurrentIndex(index: number) {
    this.currentIndex = index;
  }
  private watchCurrentSong(song: Song) {
    this.currentSong = song;
    if (song) {
      this.duration = song.dt / 1000;
    }
  }
  private watchPlayMode(mode: PlayMode) {
    this.playMode = mode;
    if (this.songList) {
      let list = this.songList.slice();
      if (mode.type === 'random') {
        list = shuffle(list);
      }
      this.changeCurrentIndex(list, this.currentSong);
      this.batchActionsService.onPlayModePlayList(list);
    }
  }
  private watchCurrentAction(action: CurrentActions) {
    const title = TipTitles[CurrentActions[action]];
    if (title) {
      this.controlToolTip.title = title;
      if (this.playerVisible === 'hide') {
        this.togglePlayerVisible('show');
      } else {
        this.showToolTip();
      }
    }
    // console.log('action:', CurrentActions[action]);
    this.batchActionsService.watchActions();
  }
  private showToolTip() {
    this.controlToolTip.show = true;
    timer(1200).subscribe(() => {
      this.controlToolTip = {
        title: '',
        show: false
      };
    });
  }
  onAnimationDone(ev: AnimationEvent) {
    this.animating = false;
    if (ev.toState === 'show' && this.controlToolTip.title) {
      this.showToolTip();
    }
  }
  private updateIndex(index: number) {
    this.batchActionsService.updateSongIndex(index);
    this.songReady = false;
  }
  private changeCurrentIndex(list: Song[], song: Song) {
    const newIndex = findIndex(list, song);
    this.updateIndex(newIndex);
  }
  private play() {
    this.audioEle.play().then();
    this.playing = true;
  }
  private makeTxt(type: string, name: string, makeBy: string | Singer[]): string {
    let needText = '';
    if (Array.isArray(makeBy)) {
      needText = makeBy.map(item => item.name).join('/');
    } else {
      needText = makeBy;
    }
    return `${type}: ${name} -- ${needText}`;
  }
  // private bindDocumentClickListener() {
  //   if (!this.winClicked) {
  //     this.winClicked = fromEvent(this.doc, 'click').subscribe(() => {
  //       if (!this.bindFlag) {
  //         this.showPanel = false;
  //         this.showVolumePanel = false;
  //         this.bindFlag = false;
  //       }
  //       this.bindFlag = false;
  //     });
  //   }
  // }
  // private unbindDocumentClickListener() {
  //   if (this.winClicked) {
  //     this.winClicked.unsubscribe();
  //     this.winClicked = null;
  //   }
  // }
  private loop() {
    this.audioEle.currentTime = 0;
    this.play();
    if (this.playerPanel) {
      this.playerPanel.seekLyric(0);
    }
  }
  onPlay(): void {
    this.songReady = true;
    this.play();
  }
  onEnd(): void {
    this.playing = false;
    if (this.playMode.type === 'singleLoop') {
      this.loop();
    } else {
      this.onNext(this.currentIndex + 1);
    }
  }
  onError() {
    this.percent = 0;
    this.bufferPercent = 0;
    this.playing = false;
  }
  // 上一曲
  onPrev(index: number) {
    if (this.songList.length && this.playMode.type === 'singleLoop') {
      this.loop();
      return;
    }
    if (!this.songReady) {
      if (this.playList.length > 1 && this.playMode.type === 'random') {
        this.updateIndex(this.playList.length - 1);
      }
      return;
    }
    if (this.playList.length === 1) {
      this.loop();
    } else {
      const newIndex = index < 0 ? this.playList.length - 1 : index;
      this.updateIndex(newIndex);
    }
  }
  // 下一曲
  onNext(index: number) {
    if (this.songList.length && this.playMode.type === 'singleLoop') {
      this.loop();
      return;
    }
    if (!this.songReady) {
      return;
    }
    if (this.playList.length === 1) {
      this.loop();
    } else {
      const newIndex = index >= this.playList.length ?  0 : index;
      this.updateIndex(newIndex);
    }
  }
  // 切换播放/暂停状态
  onToggle() {
    if (!this.currentSong) {
      if (this.playList.length) {
        this.updateIndex(0);
      }
    } else {
      if (this.songReady) {
        this.playing = !this.playing;
        if (this.playing) {
          this.audioEle.play().then();
        } else {
          this.audioEle.pause();
        }
      }
    }
  }
  onTimeUpdate(e: Event): void {
    this.currentTime = (e.target as HTMLAudioElement).currentTime;
    this.percent = (this.currentTime / this.duration) * 100;
    const buffered = this.audioEle.buffered;
    if (buffered.length && this.bufferPercent < 100) {
      this.bufferPercent = (buffered.end(0) / this.duration) * 100;
    }
  }
  onPercentChange(value: number) {
    if (this.currentSong) {
      const currentTime = this.duration * (value / 100);
      this.audioEle.currentTime = currentTime;
      if (this.playerPanel) {
        this.playerPanel.seekLyric(currentTime * 1000);
      }
    }
  }
  onClickOutside() {
    this.showPanel = false;
    this.showVolumePanel = false;
    this.bindFlag = false;
  }
  changeCurrentSong(song: Song) {
    this.changeCurrentIndex(this.playList, song);
  }
  clearSong() {
    this.nzModalServe.confirm({
      nzTitle: '确定清空列表?',
      nzOnOk: () => {
        this.batchActionsService.onClearSong();
        this.currentSong = null;
        this.currentIndex = -1;
        this.currentTime = 0;
        this.duration = 0;
      }
    });
  }
  deleteSong(song: Song) {
    this.batchActionsService.onDeleteSong(song);
  }
  // 控制音量面板/播放列表面板显示与否
  togglePanel(type: string) {
    if (type === 'showPanel' && !this.songList.length) {
      return;
    }
    this[type] = !this[type];
    this.bindFlag = (this.showVolumePanel || this.showPanel);
  }
  volumeChange(value: number) {
    this.volume = value;
    this.audioEle.volume = value / 100;
  }
  // 切换播放模式
  toggleMode() {
    this.batchActionsService.onToggleMode(++this.modeCount % 3);
  }
  // 切换播放器显示与否
  togglePlayerVisible(type: string) {
    if (!this.isLocked && !this.animating) {
      this.playerVisible = type;
    }
  }
  // 跳转
  skipToInfo(path: [string, number]) {
    if (path[0].includes('singer') && !this.user) {
      this.batchActionsService.controlModalVisible(true, ModalTypes.LoginByPhone);
      return;
    }
    this.showPanel = false;
    this.showVolumePanel = false;
    this.router.navigate(path).then();
  }
  // 分享歌曲
  onShareSong(song: Song, type = 'song') {
    if (song) {
     const txt = this.makeTxt('歌曲', song.name, song.ar);
     const info: ShareInfo = {id: song.id.toString(), type, txt};
     this.batchActionsService.setShareInfo(info);
    }
  }
  // 收藏歌曲
  onLikeSong(songs: Song | Song[]) {
    let ids = '';
    if (songs) {
      if (Array.isArray(songs)) {
        ids = songs.map(song => song.id).join(',');
      } else {
        ids = songs.id.toString();
      }
    }
    if (ids.length) {
      this.batchActionsService.likeSong(ids);
    }
  }
}
